GskKeepFunc keep_func;
GskDeleteFunc delete_func;
GskInsertFunc insert_func;
+
+ guint allow_abort : 1;
};
typedef struct _SplitResult {
return settings;
}
+void
+gsk_diff_settings_set_allow_abort (GskDiffSettings *settings,
+ gboolean allow_abort)
+{
+ settings->allow_abort = allow_abort;
+}
+
void
gsk_diff_settings_free (GskDiffSettings *settings)
{
* cases using this algorithm is full, so a little bit of heuristic is needed
* to cut the search and to return a suboptimal point.
*/
-static void
+static GskDiffResult
split (gconstpointer *elem1,
gssize off1,
gssize lim1,
spl->i1 = i1;
spl->i2 = i2;
spl->min_lo = spl->min_hi = 1;
- return;
+ return GSK_DIFF_OK;
}
}
spl->i1 = i1;
spl->i2 = i2;
spl->min_lo = spl->min_hi = 1;
- return;
+ return GSK_DIFF_OK;
}
}
/*
* If the edit cost is above the heuristic trigger and if
* we got a good snake, we sample current diagonals to see
- * if some of the, have reached an "interesting" path. Our
+ * if some of them have reached an "interesting" path. Our
* measure is a function of the distance from the diagonal
* corner (i1 + i2) penalized with the distance from the
* mid diagonal itself. If this value is above the current
{
spl->min_lo = 1;
spl->min_hi = 0;
- return;
+ return GSK_DIFF_OK;
}
for (best = 0, d = bmax; d >= bmin; d -= 2)
{
spl->min_lo = 0;
spl->min_hi = 1;
- return;
+ return GSK_DIFF_OK;
}
}
{
gssize fbest, fbest1, bbest, bbest1;
+ if (settings->allow_abort)
+ return GSK_DIFF_ABORTED;
+
fbest = fbest1 = -1;
for (d = fmax; d >= fmin; d -= 2)
{
spl->min_hi = 1;
}
- return;
+ return GSK_DIFF_OK;
}
}
}
* the box splitting function. Note that the real job (marking changed lines)
* is done in the two boundary reaching checks.
*/
-static void
+static GskDiffResult
compare (gconstpointer *elem1,
gssize off1,
gssize lim1,
else
{
SplitResult spl = { 0, };
+ GskDiffResult res;
/*
* Divide ...
*/
- split (elem1, off1, lim1,
- elem2, off2, lim2,
- kvdf, kvdb, need_min,
- settings, data,
- &spl);
+ res = split (elem1, off1, lim1,
+ elem2, off2, lim2,
+ kvdf, kvdb, need_min,
+ settings, data,
+ &spl);
+ if (res != GSK_DIFF_OK)
+ return res;
+
/*
* ... et Impera.
*/
- compare (elem1, off1, spl.i1,
- elem2, off2, spl.i2,
- kvdf, kvdb, spl.min_lo,
- settings, data);
- compare (elem1, spl.i1, lim1,
- elem2, spl.i2, lim2,
- kvdf, kvdb, spl.min_hi,
- settings, data);
+ res = compare (elem1, off1, spl.i1,
+ elem2, off2, spl.i2,
+ kvdf, kvdb, spl.min_lo,
+ settings, data);
+ if (res != GSK_DIFF_OK)
+ return res;
+ res = compare (elem1, spl.i1, lim1,
+ elem2, spl.i2, lim2,
+ kvdf, kvdb, spl.min_hi,
+ settings, data);
+ if (res != GSK_DIFF_OK)
+ return res;
}
+
+ return GSK_DIFF_OK;
}
#if 0
dd2.rindex = xe->xdf2.rindex;
#endif
-void
+GskDiffResult
gsk_diff (gconstpointer *elem1,
gsize n1,
gconstpointer *elem2,
{
gsize ndiags;
gssize *kvd, *kvdf, *kvdb;
+ GskDiffResult res;
ndiags = n1 + n2 + 3;
kvdf += n2 + 1;
kvdb += n2 + 1;
- compare (elem1, 0, n1,
- elem2, 0, n2,
- kvdf, kvdb, FALSE,
- settings, data);
+ res = compare (elem1, 0, n1,
+ elem2, 0, n2,
+ kvdf, kvdb, FALSE,
+ settings, data);
g_free (kvd);
+
+ return res;
}
G_BEGIN_DECLS
+typedef enum {
+ GSK_DIFF_OK = 0,
+ GSK_DIFF_ABORTED,
+} GskDiffResult;
+
typedef void (* GskKeepFunc) (gconstpointer elem1, gconstpointer elem2, gpointer data);
typedef void (* GskDeleteFunc) (gconstpointer elem, gsize idx, gpointer data);
typedef void (* GskInsertFunc) (gconstpointer elem, gsize idx, gpointer data);
GskDeleteFunc delete_func,
GskInsertFunc insert_func);
void gsk_diff_settings_free (GskDiffSettings *settings);
+void gsk_diff_settings_set_allow_abort (GskDiffSettings *settings,
+ gboolean allow_abort);
-void gsk_diff (gconstpointer *elem1,
+GskDiffResult gsk_diff (gconstpointer *elem1,
gsize n1,
gconstpointer *elem2,
gsize n2,
gsk_container_node_keep_func,
gsk_container_node_change_func,
gsk_container_node_change_func);
+ gsk_diff_settings_set_allow_abort (settings, TRUE);
return settings;
}
GskContainerNode *self1 = (GskContainerNode *) node1;
GskContainerNode *self2 = (GskContainerNode *) node2;
- gsk_diff ((gconstpointer *) self1->children,
- self1->n_children,
- (gconstpointer *) self2->children,
- self2->n_children,
- gsk_container_node_get_diff_settings (),
- region);
+ if (gsk_diff ((gconstpointer *) self1->children,
+ self1->n_children,
+ (gconstpointer *) self2->children,
+ self2->n_children,
+ gsk_container_node_get_diff_settings (),
+ region) == GSK_DIFF_OK)
+ return;
+
+ gsk_render_node_diff_impossible (node1, node2, region);
}
static void